﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Compiled_Tests.Utils;

namespace Tedds_Tool
{
    public class ScriptFinder : IScriptFinder
    {
        public ISettings settings;
        private const String TTL_EXT = ".LEETSp34k";
        private const String RB_EXT = ".rb";
        private const String RULE_EXT = ".rule";
        private const String CS_EXT = ".cs";
        
        public ScriptFinder(ISettings settings)
        {
            this.settings = settings;
        }

        public System.IO.TextReader FindPrecondition(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Preconditions/" + name + TTL_EXT;
            return getReader(filePath);
        }

        public System.IO.TextReader FindImplication(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Implications/" + name + TTL_EXT;
            return getReader(filePath);
        }

        public System.IO.TextReader FindConsequence(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Consequences/" + name + TTL_EXT;
            return getReader(filePath);
        }

        [Obsolete("FindTestScript is obsolete please use Find(AcceptanceTest|BuisnessLogic|RawUIScript) instead.", false)]
        public System.IO.TextReader FindTestScript(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Tests/" + name + TTL_EXT;
            return getReader(filePath);
        }

        public System.IO.TextReader FindRuleBase(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/RuleBases/" + name + RB_EXT;
            return getReader(filePath);
        }

        public System.IO.TextReader FindRule(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Rules/" + name + RULE_EXT;
            return getReader(filePath);
        }

        public System.IO.TextWriter CreatePrecondition(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Preconditions/" + name + TTL_EXT;
            return getWriter(filePath);
        }

        public System.IO.TextWriter CreateAction(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Implications/" + name + TTL_EXT;
            return getWriter(filePath);
        }

        public System.IO.TextWriter CreateConsequence(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Consequences/" + name + TTL_EXT;
            return getWriter(filePath);
        }

        [Obsolete("CreateTestScript is obsolete please use Create(AcceptanceTest|BuisnessLogic|RawUIScript) instead.", false)]
        public System.IO.TextWriter CreateTestScript(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Tests/" + name + TTL_EXT;
            return getWriter(filePath);
        }

        public System.IO.TextWriter CreateRuleBase(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/RuleBases/" + name + RB_EXT;
            return getWriter(filePath);
        }

        public System.IO.TextWriter CreateRule(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Rules/" + name + RULE_EXT;
            return getWriter(filePath);
        }

        public IEnumerable<string> ListPreconditions()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Preconditions");
        }

        public IEnumerable<string> ListActions()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Implications");
        }

        public IEnumerable<string> ListConsequences()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Consequences");
        }

        [Obsolete("ListTestScripts is obsolete please use List(AcceptanceTest|BuisnessLogic|RawUIScript) instead.", false)]
        public IEnumerable<string> ListTestScripts()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Tests");
        }

        public IEnumerable<string> ListRuleBases()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/RuleBases");
        }

        public IEnumerable<string> ListRules()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Rules");
        }

        public IEnumerable<string> ListTestRunners()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_UNIT_TESTS");
        }

        internal IEnumerable<String> List(String dirPath)
        {
            Directory.CreateDirectory(dirPath);
            IEnumerable<string> dir = Directory.EnumerateFiles(dirPath);
            foreach (String file in dir)
            {
                yield return Path.GetFileNameWithoutExtension(file);
            }
        }

        internal TextReader getReader(string path)
        {
            FileInfo fInfo = new FileInfo(path);
            
            ///// Backwards compatibility /////// remove after v201201xx-stable release
            String old_ext_path = Path.Combine(fInfo.Directory.FullName, Path.GetFileNameWithoutExtension(path)) + ".ttl";
            if (File.Exists(old_ext_path))
            {
                File.Move(old_ext_path, path);
            }
            ///////////////////////////////////////////////////////////////////////

            fInfo.Directory.Create();
            if (File.Exists(path))
            {
                return new StreamReader(path, Encoding.ASCII);
            }
            else
            {
                //TODO: handle this exception
                throw new FileNotFoundException();
            }
        }

        internal TextWriter getWriter(string path)
        {
            FileInfo fi = new FileInfo(path);
            fi.Directory.Create();
            if(fi.Exists)
                fi.IsReadOnly = false;
            return new StreamWriter(path, false, Encoding.ASCII);
        }



        public TextWriter WriteTestClass(string name)
        {
            return getWriter(settings.ProjectRoot.FullName + "/LEET_UNIT_TESTS/Tests/" + name + CS_EXT);
        }

        public void DeleteRuleBase(string name)
        {
            File.Delete(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/RuleBases/" + name + RB_EXT);
        }

        public void DeleteRule(string name)
        {
            File.Delete(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Rules/" + name + RULE_EXT);
        }

        public void DeleteTestRunner(string name)
        {
            File.Delete(settings.ProjectRoot.FullName + "/LEET_UNIT_TESTS/" + name + CS_EXT);
        }


        public TextReader FindAcceptanceTest(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/AcceptanceTests/" + name + TTL_EXT;
            ///// Backwards compatibility /////// remove after v201201xx-stable release
            if (!File.Exists(filePath))
            {
                 string oldPath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Tests/" + name + TTL_EXT;
                 File.Move(oldPath, filePath);
            }
            ///////////////////////////////////////////////////////////////////////////
            return getReader(filePath);
        }

        public TextReader FindBuisnessLogic(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/BuisnessLogic/" + name + TTL_EXT;
            ///// Backwards compatibility /////// remove after v201201xx-stable release
            if (!File.Exists(filePath))
            {
                string oldPath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Tests/" + name + TTL_EXT;
                File.Move(oldPath, filePath);
            }
            ///////////////////////////////////////////////////////////////////////////
            return getReader(filePath);
        }

        public TextReader FindRawUIScript(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/RawUIScript/" + name + TTL_EXT;
            ///// Backwards compatibility /////// remove after v201201xx-stable release
            if (!File.Exists(filePath))
            {
                string oldPath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/Tests/" + name + TTL_EXT;
                File.Move(oldPath, filePath);
            }
            ///////////////////////////////////////////////////////////////////////////
            return getReader(filePath);
        }
            
        public TextWriter CreateAcceptanceTest(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/AcceptanceTests/" + name + TTL_EXT;
            return getWriter(filePath);
        }

        public TextWriter CreateBuisnessLogic(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/BuisnessLogic/" + name + TTL_EXT;
            return getWriter(filePath);
        }

        public TextWriter CreateRawUIScript(string name)
        {
            string filePath = settings.ProjectRoot.FullName + "/LEET_SCRIPTS/RawUIScript/" + name + TTL_EXT;
            return getWriter(filePath);
        }

        public IEnumerable<string> ListAcceptanceTest()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/AcceptanceTests");
        }

        public IEnumerable<string> ListBuisnessLogic()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/BuisnessLogic");
        }

        public IEnumerable<string> ListRawUIScript()
        {
            return List(settings.ProjectRoot.FullName + "/LEET_SCRIPTS/RawUIScript");
        }
    }
}
